<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  <title>CoreData的优化 | 素墨文胤</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="//我对 mmDao 进行了修改，最终代码放在了：https://github.com/godera/HDCoreDataWrapper
【转帖，有修改】在多线程环境中使用CoreDataBY 子非鱼 · 2014 年 10 月 13 日
上回书说道，其实 CoreData 学起来也没有很复杂，它的增、删、改、查和别的 ORM 大同小异。但是世界总是很复杂的，一根筋的去考虑问题很容易卡到蛋，默认情">
<meta property="og:type" content="article">
<meta property="og:title" content="CoreData的优化">
<meta property="og:url" content="http://godera.org/2015/11/10/CoreData的优化/index.html">
<meta property="og:site_name" content="素墨文胤">
<meta property="og:description" content="//我对 mmDao 进行了修改，最终代码放在了：https://github.com/godera/HDCoreDataWrapper
【转帖，有修改】在多线程环境中使用CoreDataBY 子非鱼 · 2014 年 10 月 13 日
上回书说道，其实 CoreData 学起来也没有很复杂，它的增、删、改、查和别的 ORM 大同小异。但是世界总是很复杂的，一根筋的去考虑问题很容易卡到蛋，默认情">
<meta property="og:updated_time" content="2016-01-14T06:33:27.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="CoreData的优化">
<meta name="twitter:description" content="//我对 mmDao 进行了修改，最终代码放在了：https://github.com/godera/HDCoreDataWrapper
【转帖，有修改】在多线程环境中使用CoreDataBY 子非鱼 · 2014 年 10 月 13 日
上回书说道，其实 CoreData 学起来也没有很复杂，它的增、删、改、查和别的 ORM 大同小异。但是世界总是很复杂的，一根筋的去考虑问题很容易卡到蛋，默认情">
  
  
    <link rel="icon" href="/favicon.png">
  

  <link rel="stylesheet" href="/css/style.css">
  
    <link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
  
  
    <link rel="stylesheet" href="/scrollLoading/style.css">
  
  


  

  
    <link href='//fonts.useso.com/css?family=Titillium+Web:300,400,600' rel='stylesheet' type='text/css'>
    <link href="//fonts.useso.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  <link rel="stylesheet" href="/font-awesome/css/font-awesome.min.css">
</head>

<body>
  <div id="wrap">
    <header id="header">
  <div id="header-outer" class="outer">
    <div class="container">
      <div class="container-inner">
        <div id="header-title">
          <h1 class="logo-wrap">
            <a href="/" class="logo"></a>
          </h1>
          
            <h2 class="subtitle-wrap">
              <p class="subtitle">一日心静一日仙，不以神力乱人间。</p>
            </h2>
          
        </div>
        <div id="header-inner" class="nav-container">
          <a id="main-nav-toggle" class="nav-icon fa fa-bars"></a>
          <div class="nav-container-inner">
            <ul id="main-nav">
              
                <li class="main-nav-list-item" ><a class="main-nav-list-link" href="/">Home</a></li>
              
                    <ul class="main-nav-list"><li class="main-nav-list-item"><a class="main-nav-list-link" href="/categories/JS/">JS</a></li><li class="main-nav-list-item"><a class="main-nav-list-link" href="/categories/Unix-Linux/">Unix_Linux</a></li><li class="main-nav-list-item"><a class="main-nav-list-link" href="/categories/iOS/">iOS</a></li><li class="main-nav-list-item"><a class="main-nav-list-link" href="/categories/哲学辨思/">哲学辨思</a></li><li class="main-nav-list-item"><a class="main-nav-list-link" href="/categories/数据库/">数据库</a></li><li class="main-nav-list-item"><a class="main-nav-list-link" href="/categories/文字文化/">文字文化</a></li><li class="main-nav-list-item"><a class="main-nav-list-link" href="/categories/生活感悟/">生活感悟</a></li><li class="main-nav-list-item"><a class="main-nav-list-link" href="/categories/随心随性/">随心随性</a></li><li class="main-nav-list-item"><a class="main-nav-list-link" href="/categories/默认标签/">默认标签</a></li></ul>
                  
                <li class="main-nav-list-item" ><a class="main-nav-list-link" href="/about/index.html">About</a></li>
              
            </ul>
            <nav id="sub-nav">
              <div id="search-form-wrap">
                
                  <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" results="0" class="search-form-input" placeholder="Search"><input type="hidden" name="sitesearch" value="http://godera.org"></form>
                
              </div>
            </nav>
          </div>
        </div>
      </div>
    </div>
  </div>
</header>
    <div class="container">
      <div class="main-body container-inner">
        <div class="main-body-inner">
          <section id="main">
            <div class="main-body-header">

              <h1 class="header"><a class="page-title-link" href="/categories/iOS/">iOS</a></h1>
            </div>
            <div class="main-body-content">
              
  <article id="post-CoreData的优化" class="article article-single article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
      <!--  -->
      
        <header class="article-header">
          
  
    <h1 class="article-title" itemprop="name">
      CoreData的优化
    </h1>
  

        </header>
      
      <p class="article-byline">
        <a href="/2015/11/10/CoreData的优化/" class="article-date">
  <time datetime="2015-11-10T04:31:53.000Z" itemprop="datePublished">2015-11-10</time>
</a>
      </p>
      <div class="article-entry" itemprop="articleBody">
        <p>//我对 mmDao 进行了修改，最终代码放在了：<a href="https://github.com/godera/HDCoreDataWrapper" target="_blank" rel="external">https://github.com/godera/HDCoreDataWrapper</a></p>
<p>【转帖，有修改】在多线程环境中使用CoreData<br>BY 子非鱼 · 2014 年 10 月 13 日</p>
<p>上回书说道，其实 CoreData 学起来也没有很复杂，它的增、删、改、查和别的 ORM 大同小异。但是世界总是很复杂的，一根筋的去考虑问题很容易卡到蛋，默认情况下我们的代码都在 Main Thread 中执行，数据库操作一旦量多了，频繁了，势必会阻塞住主线程的其他操作，俗语说—卡住了。</p>
<p>这个世界天然是多线程的，所以我们操作数据也必须多线程。CoreData 对多线程的支持比较奇怪（按照一般的思路来说），CoreData 的 NSPersistentStoreCoordinator 和 NSManagedObjectContext 对象都是不能跨线程使用的，NSManagedObject 也不行。有人想：加把锁不就完了？No！作为一个处女座是不能忍受这么丑陋的解决方案的。其实 NSManagedObjectContext 已经对跨线程提供了内置的支持，只不过方式比较特殊，需要脑洞大开才行。<br><a id="more"></a><br>在创建 NSManagedObject 的时候有个构造器参数 initWithConcurrencyType 就是解决的关键所在，这个参数是一个枚举，有三个可选值：<br>NSConfinementConcurrencyType (或者不加参数，默认就是这个)<br>NSMainQueueConcurrencyType (表示只会在主线程中执行)<br>NSPrivateQueueConcurrencyType (表示可以在子线程中执行)<br>那么究竟应该怎么使用才能无阻塞无痛感呢？</p>
<p>经过参考： <a href="http://www.cocoanetics.com/2012/07/multi-context-coredata/" target="_blank" rel="external">http://www.cocoanetics.com/2012/07/multi-context-coredata/</a> （此文甚好）这篇文章，我们使用三层 NSManagedObjectContext 嵌套的方式。</p>
<p>NSManagedObjectContext 是可以基于其他的 NSManagedObjectContext 的，通过 setParentContext 方法，可以设置另外一个 NSManagedObjectContext 为自己的父级，这个时候子级可以访问父级下所有的对象，而且子级 NSManagedObjectContext 的内容变化后，如果执行 save 方法，会自动的 merge 到父级 NSManagedObjectContext 中，也就是子级save后，变动会同步到父级 NSManagedObjectContext。当然这个时候父级也必须再 save 一次，如果父级没有父级了，那么就会直接向 NSPersistentStoreCoordinator 中 写入，如果有就会接着向再上一层的父级冒泡……</p>
<p>那么这里如同参考的文章一样，通过三个级别的 NSManagedObjectContext， 一个负责在 background 更新 NSPersistentStoreCoordinator。一个用在主线程，主要执行插入，修改和删除操作，一些小的查询也可以在这里同步执行，如果有大的查询，就起一个新的 NSPrivateQueueConcurrencyType 类型的 NSManagedObjectContext，然后放在后台去执行查询，查询完成后将结果返回主线程。</p>
<p>NSManagedObjectContext 在后台线程执行是通过 performBlock 方法来实现的，在传入的匿名 block 中执行的代码就是在子线程中了，比如<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">[_bgObjectContext performBlock:^&#123;</div><div class="line">NSError *inner_error = nil;</div><div class="line">[_bgObjectContext save:&amp;inner_error];</div><div class="line">&#125;];</div></pre></td></tr></table></figure></p>
<p>那么如果是查询的话，因为 NSManagedObject 也不能跨线程访问，所以在 block 里获取到的 NSManagedObject 对象只能将 objectid 传到主线程，主线程再通过 objectWithID 恢复对象的方法，如下面的示例：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line">+(void)one:(NSString*)predicate on:(ObjectResult)handler&#123;</div><div class="line">NSManagedObjectContext *ctx = [[mmDAO instance] createPrivateObjectContext];</div><div class="line">[ctx performBlock:^&#123;</div><div class="line">NSFetchRequest *fetchRequest = [self makeRequest:ctx predicate:predicate orderby:nil offset:0 limit:1];</div><div class="line">NSError* error = nil;</div><div class="line">NSArray* results = [ctx executeFetchRequest:fetchRequest error:&amp;amp;error];</div><div class="line">if (error) &#123;</div><div class="line">NSLog(@&quot;error: %@&quot;, error);</div><div class="line">[[mmDAO instance].mainObjectContext performBlock:^&#123;</div><div class="line">handler(@[], nil);</div><div class="line">&#125;];</div><div class="line">&#125;</div><div class="line">if ([results count]&amp;lt;1) &#123;</div><div class="line">[[mmDAO instance].mainObjectContext performBlock:^&#123;</div><div class="line">handler(@[], nil);</div><div class="line">&#125;];</div><div class="line">&#125;</div><div class="line">NSManagedObjectID *objId = ((NSManagedObject*)results[0]).objectID;</div><div class="line">[[mmDAO instance].mainObjectContext performBlock:^&#123;</div><div class="line">handler([[mmDAO instance].mainObjectContext objectWithID:objId], nil);</div><div class="line">&#125;];</div><div class="line">&#125;];</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>最后我们将上述的要点结合起来，解决方案就呼之欲出了。</p>
<p>首先我们还是需要一个抽象存储和数据操作的核心<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div></pre></td><td class="code"><pre><div class="line">mmDAO.h</div><div class="line">#import &lt;Foundation/Foundation.h&gt;</div><div class="line"> </div><div class="line">typedef void(^OperationResult)(NSError* error);</div><div class="line"> </div><div class="line">@interface mmDAO : NSObject</div><div class="line">@property (readonly, strong, nonatomic) NSOperationQueue *queue;</div><div class="line">@property (readonly ,strong, nonatomic) NSManagedObjectContext *bgObjectContext;</div><div class="line">@property (readonly, strong, nonatomic) NSManagedObjectContext *mainObjectContext;</div><div class="line"> </div><div class="line">+(mmDAO*)instance;</div><div class="line">-(void) setupEnvModel:(NSString *)model DbFile:(NSString*)filename;</div><div class="line">- (NSManagedObjectContext *)createPrivateObjectContext;</div><div class="line">-(NSError*)save:(OperationResult)handler;</div><div class="line"> </div><div class="line">@end</div><div class="line"></div><div class="line"></div><div class="line">mmDAO.m</div><div class="line"></div><div class="line">#import &quot;mmDAO.h&quot;</div><div class="line">#import &quot;mmAppDelegate.h&quot;</div><div class="line"> </div><div class="line">static mmDAO *onlyInstance;</div><div class="line"> </div><div class="line">@interface mmDAO ()</div><div class="line">@property (nonatomic, copy)NSString *modelName;</div><div class="line">@property (nonatomic, copy)NSString *dbFileName;</div><div class="line">@end</div><div class="line"> </div><div class="line">@implementation mmDAO</div><div class="line">+(mmDAO*)instance&#123;</div><div class="line">static dispatch_once_t onceToken;</div><div class="line">dispatch_once(&amp;amp;onceToken, ^&#123;</div><div class="line">onlyInstance = [[mmDAO alloc] init];</div><div class="line">&#125;);</div><div class="line">return onlyInstance;</div><div class="line">&#125;</div><div class="line"> </div><div class="line">- (instancetype)init</div><div class="line">&#123;</div><div class="line">self = [super init];</div><div class="line">if (self) &#123;</div><div class="line">&#125;</div><div class="line">return self;</div><div class="line">&#125;</div><div class="line"> </div><div class="line">-(void) setupEnvModel:(NSString *)model DbFile:(NSString*)filename&#123;</div><div class="line">_modelName = model;</div><div class="line">_dbFileName = filename;</div><div class="line">[self initCoreDataStack];</div><div class="line">&#125;</div><div class="line"> </div><div class="line">- (void)initCoreDataStack</div><div class="line">&#123;</div><div class="line">NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];</div><div class="line">if (coordinator != nil) &#123;</div><div class="line">_bgObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];</div><div class="line">[_bgObjectContext setPersistentStoreCoordinator:coordinator];</div><div class="line"> </div><div class="line">_mainObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];</div><div class="line">[_mainObjectContext setParentContext:_bgObjectContext];</div><div class="line">&#125;</div><div class="line"> </div><div class="line">&#125;</div><div class="line"> </div><div class="line">- (NSManagedObjectContext *)createPrivateObjectContext</div><div class="line">&#123;</div><div class="line">NSManagedObjectContext *ctx = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];</div><div class="line">[ctx setParentContext:_mainObjectContext];</div><div class="line"> </div><div class="line">return ctx;</div><div class="line">&#125;</div><div class="line"> </div><div class="line">- (NSManagedObjectModel *)managedObjectModel</div><div class="line">&#123;</div><div class="line">NSManagedObjectModel *managedObjectModel;</div><div class="line">NSURL *modelURL = [[NSBundle mainBundle] URLForResource:_modelName withExtension:@&quot;momd&quot;];</div><div class="line">managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];</div><div class="line">return managedObjectModel;</div><div class="line">&#125;</div><div class="line"> </div><div class="line">- (NSPersistentStoreCoordinator *)persistentStoreCoordinator</div><div class="line">&#123;</div><div class="line">NSPersistentStoreCoordinator *persistentStoreCoordinator = nil;</div><div class="line">NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:_dbFileName];</div><div class="line"> </div><div class="line">NSError *error = nil;</div><div class="line">persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];</div><div class="line">if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&amp;amp;error]) &#123;</div><div class="line">NSLog(@&quot;Unresolved error %@, %@&quot;, error, [error userInfo]);</div><div class="line">abort();</div><div class="line">&#125;</div><div class="line">return persistentStoreCoordinator;</div><div class="line">&#125;</div><div class="line"> </div><div class="line">- (NSURL *)applicationDocumentsDirectory</div><div class="line">&#123;</div><div class="line">return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];</div><div class="line">&#125;</div><div class="line"> </div><div class="line">-(NSError*)save:(OperationResult)handler&#123;</div><div class="line">NSError *error;</div><div class="line">if ([_mainObjectContext hasChanges]) &#123;</div><div class="line">[_mainObjectContext save:&amp;amp;error];</div><div class="line">[_bgObjectContext performBlock:^&#123;</div><div class="line">__block NSError *inner_error = nil;</div><div class="line">[_bgObjectContext save:&amp;amp;inner_error];</div><div class="line">if (handler)&#123;</div><div class="line">//handler(error);</div><div class="line">//这里需要返回主线程，不然在回调里操作界面会出错</div><div class="line">[_mainObjectContext performBlock:^&#123;</div><div class="line">handler(error);</div><div class="line">&#125;];</div><div class="line">&#125;</div><div class="line">&#125;];</div><div class="line">&#125;</div><div class="line">return error;</div><div class="line">&#125;</div><div class="line"> </div><div class="line">@end</div></pre></td></tr></table></figure></p>
<p>然后我们扩展 NSManagedObject，把操作注入到类里，这样子有个好处是可以自动获取类名，然后就不用子级写字符串的类名了。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div><div class="line">126</div><div class="line">127</div><div class="line">128</div><div class="line">129</div><div class="line">130</div><div class="line">131</div><div class="line">132</div><div class="line">133</div><div class="line">134</div><div class="line">135</div><div class="line">136</div><div class="line">137</div><div class="line">138</div><div class="line">139</div><div class="line">140</div><div class="line">141</div><div class="line">142</div><div class="line">143</div><div class="line">144</div><div class="line">145</div><div class="line">146</div><div class="line">147</div><div class="line">148</div><div class="line">149</div><div class="line">150</div><div class="line">151</div><div class="line">152</div><div class="line">153</div><div class="line">154</div><div class="line">155</div><div class="line">156</div><div class="line">157</div></pre></td><td class="code"><pre><div class="line">NSManagedObject+helper.h</div><div class="line"></div><div class="line">typedef void(^ListResult)(NSArray* result, NSError *error);</div><div class="line">typedef void(^ObjectResult)(id result, NSError *error);</div><div class="line"> </div><div class="line">#import &lt;CoreData/CoreData.h&gt;</div><div class="line">#import &quot;mmDAO.h&quot;</div><div class="line"> </div><div class="line">@interface NSManagedObject (helper)</div><div class="line"> </div><div class="line">+(id)createNew;</div><div class="line"> </div><div class="line">+(NSError*)save:(OperationResult)handler;</div><div class="line"> </div><div class="line">+(NSArray*)filter:(NSString *)predicate orderby:(NSArray *)orders offset:(int)offset limit:(int)limit;</div><div class="line"> </div><div class="line">+(void)filter:(NSString *)predicate orderby:(NSArray *)orders offset:(int)offset limit:(int)limit on:(ListResult)handler;</div><div class="line"> </div><div class="line">+(id)one:(NSString*)predicate;</div><div class="line"> </div><div class="line">+(void)one:(NSString*)predicate on:(ObjectResult)handler;</div><div class="line"> </div><div class="line">+(void)delobject:(id)object;</div><div class="line">@end</div><div class="line"></div><div class="line"></div><div class="line">NSManagedObject+helper.m</div><div class="line"></div><div class="line">#import &quot;NSManagedObject+helper.h&quot;</div><div class="line"> </div><div class="line">@implementation NSManagedObject (helper)</div><div class="line">+(id)createNew&#123;</div><div class="line">    NSString *className = [NSString stringWithUTF8String:object_getClassName(self)];</div><div class="line">    return [NSEntityDescription insertNewObjectForEntityForName:className inManagedObjectContext:[mmDAO instance].mainObjectContext];</div><div class="line">&#125;</div><div class="line"> </div><div class="line">+(NSError*)save:(OperationResult)handler&#123;</div><div class="line">    return [[mmDAO instance] save:handler];</div><div class="line">&#125;</div><div class="line"> </div><div class="line">+(NSArray*)filter:(NSString *)predicate orderby:(NSArray *)orders offset:(int)offset limit:(int)limit&#123;</div><div class="line"> </div><div class="line">    NSManagedObjectContext *ctx = [mmDAO instance].mainObjectContext;</div><div class="line">    NSFetchRequest *fetchRequest = [self makeRequest:ctx predicate:predicate orderby:orders offset:offset limit:limit];</div><div class="line"> </div><div class="line">    NSError* error = nil;</div><div class="line">    NSArray* results = [ctx executeFetchRequest:fetchRequest error:&amp;error];</div><div class="line">    if (error) &#123;</div><div class="line">        NSLog(@&quot;error: %@&quot;, error);</div><div class="line">        return @[];</div><div class="line">    &#125;</div><div class="line">    return results;</div><div class="line">&#125;</div><div class="line"> </div><div class="line">+(NSFetchRequest*)makeRequest:(NSManagedObjectContext*)ctx predicate:(NSString*)predicate orderby:(NSArray*)orders offset:(int)offset limit:(int)limit&#123;</div><div class="line">    NSString *className = [NSString stringWithUTF8String:object_getClassName(self)];</div><div class="line">    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];</div><div class="line">    [fetchRequest setEntity:[NSEntityDescription entityForName:className inManagedObjectContext:ctx]];</div><div class="line">    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:predicate]];</div><div class="line">    NSMutableArray *orderArray = [[NSMutableArray alloc] init];</div><div class="line">    if (orders!=nil) &#123;</div><div class="line">        for (NSString *order in orders) &#123;</div><div class="line">            NSSortDescriptor *orderDesc = nil;</div><div class="line">            if ([[order substringToIndex:1] isEqualToString:@&quot;-&quot;]) &#123;</div><div class="line">                orderDesc = [[NSSortDescriptor alloc] initWithKey:[order substringFromIndex:1]</div><div class="line">                                                        ascending:NO];</div><div class="line">            &#125;else&#123;</div><div class="line">                orderDesc = [[NSSortDescriptor alloc] initWithKey:order</div><div class="line">                                                        ascending:YES];</div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line">        [fetchRequest setSortDescriptors:orderArray];</div><div class="line">    &#125;</div><div class="line">    if (offset&gt;0) &#123;</div><div class="line">        [fetchRequest setFetchOffset:offset];</div><div class="line">    &#125;</div><div class="line">    if (limit&gt;0) &#123;</div><div class="line">        [fetchRequest setFetchLimit:limit];</div><div class="line">    &#125;</div><div class="line">    return fetchRequest;</div><div class="line">&#125;</div><div class="line"> </div><div class="line">+(void)filter:(NSString *)predicate orderby:(NSArray *)orders offset:(int)offset limit:(int)limit on:(ListResult)handler&#123;</div><div class="line"> </div><div class="line">    NSManagedObjectContext *ctx = [[mmDAO instance] createPrivateObjectContext];</div><div class="line">    [ctx performBlock:^&#123;</div><div class="line">        NSFetchRequest *fetchRequest = [self makeRequest:ctx predicate:predicate orderby:orders offset:offset limit:limit];</div><div class="line">        NSError* error = nil;</div><div class="line">        NSArray* results = [ctx executeFetchRequest:fetchRequest error:&amp;error];</div><div class="line">        if (error) &#123;</div><div class="line">            NSLog(@&quot;error: %@&quot;, error);</div><div class="line">            [[mmDAO instance].mainObjectContext performBlock:^&#123;</div><div class="line">                handler(@[], nil);</div><div class="line">            &#125;];</div><div class="line">        &#125;</div><div class="line">        if ([results count]&lt;1) &#123;</div><div class="line">            [[mmDAO instance].mainObjectContext performBlock:^&#123;</div><div class="line">                handler(@[], nil);</div><div class="line">            &#125;];</div><div class="line">        &#125;</div><div class="line">        NSMutableArray *result_ids = [[NSMutableArray alloc] init];</div><div class="line">        for (NSManagedObject *item  in results) &#123;</div><div class="line">            NSLog(@&quot;id=%@&quot;, item.objectID);</div><div class="line">            [result_ids addObject:item.objectID];</div><div class="line">        &#125;</div><div class="line">        [[mmDAO instance].mainObjectContext performBlock:^&#123;</div><div class="line">            NSMutableArray *final_results = [[NSMutableArray alloc] init];</div><div class="line">            for (NSManagedObjectID *oid in result_ids) &#123;</div><div class="line">                [final_results addObject:[[mmDAO instance].mainObjectContext objectWithID:oid]];</div><div class="line">            &#125;</div><div class="line">            handler(final_results, nil);</div><div class="line">        &#125;];</div><div class="line">    &#125;];</div><div class="line">&#125;</div><div class="line"> </div><div class="line">+(id)one:(NSString*)predicate&#123;</div><div class="line">    NSManagedObjectContext *ctx = [mmDAO instance].mainObjectContext;</div><div class="line">    NSFetchRequest *fetchRequest = [self makeRequest:ctx predicate:predicate orderby:nil offset:0 limit:1];</div><div class="line">    NSError* error = nil;</div><div class="line">    NSArray* results = [ctx executeFetchRequest:fetchRequest error:&amp;error];</div><div class="line">    if ([results count]!=1) &#123;</div><div class="line">        raise(1);</div><div class="line">    &#125;</div><div class="line">    return results[0];</div><div class="line">&#125;</div><div class="line"> </div><div class="line">+(void)one:(NSString*)predicate on:(ObjectResult)handler&#123;</div><div class="line">    NSManagedObjectContext *ctx = [[mmDAO instance] createPrivateObjectContext];</div><div class="line">    [ctx performBlock:^&#123;</div><div class="line">        NSFetchRequest *fetchRequest = [self makeRequest:ctx predicate:predicate orderby:nil offset:0 limit:1];</div><div class="line">        NSError* error = nil;</div><div class="line">        NSArray* results = [ctx executeFetchRequest:fetchRequest error:&amp;error];</div><div class="line">        if (error) &#123;</div><div class="line">            NSLog(@&quot;error: %@&quot;, error);</div><div class="line">            [[mmDAO instance].mainObjectContext performBlock:^&#123;</div><div class="line">                handler(@[], nil);</div><div class="line">            &#125;];</div><div class="line">        &#125;</div><div class="line">        if ([results count]&lt;1) &#123;</div><div class="line">            [[mmDAO instance].mainObjectContext performBlock:^&#123;</div><div class="line">                handler(@[], nil);</div><div class="line">            &#125;];</div><div class="line">        &#125;</div><div class="line">        NSManagedObjectID *objId = ((NSManagedObject*)results[0]).objectID;</div><div class="line">        [[mmDAO instance].mainObjectContext performBlock:^&#123;</div><div class="line">            handler([[mmDAO instance].mainObjectContext objectWithID:objId], nil);</div><div class="line">        &#125;];</div><div class="line">    &#125;];</div><div class="line">&#125;</div><div class="line"> </div><div class="line">+(void)delobject:(id)object&#123;</div><div class="line">    //[[mmDAO instance].mainObjectContext delete:object];</div><div class="line">    //这里方法名写错了</div><div class="line">    [[mmDAO instance].mainObjectContext deleteObject:object];</div><div class="line">&#125;</div><div class="line"> </div><div class="line">@end</div></pre></td></tr></table></figure></p>
<p>本文内容已经打包放在了github，有兴趣的可以fork下来直接用 <a href="https://github.com/ipconfiger/asyncCoreDataWrapper" target="_blank" rel="external">https://github.com/ipconfiger/asyncCoreDataWrapper</a></p>
<p>另，文中代码有两处错误，已经加上了注释，提前看了的同学记得以github为准。</p>
<p>from:<a href="http://liming.me/2014/06/25/noblocking-coredata-in-multithread/" target="_blank" rel="external">http://liming.me/2014/06/25/noblocking-coredata-in-multithread/</a></p>

      </div>
      <footer class="article-footer">
        <a data-url="http://godera.org/2015/11/10/CoreData的优化/" data-id="ciw7o5qh300063refcds3sg4n" class="article-share-link"><i class="fa fa-share"></i>Share</a>
        
        
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/iOS/">iOS</a></li></ul>

      </footer>
    </div>
  </article>
  
  


<!--高速版-->
<div id="SOHUCS"></div>
<script charset="utf-8" type="text/javascript" src="http://changyan.sohu.com/upload/changyan.js" ></script>
<script type="text/javascript">
    window.changyan.api.config({
        appid: 'cys5Qvajj',
        conf: 'prod_62197afb84b42bd16c642feedaaef9f1'
    });
</script>   

            </div>
          </section>
          <aside id="sidebar">
  <a class="sidebar-toggle" title="Expand Sidebar"><i class="toggle icon"></i></a>
  <div class="sidebar-top">
    <p>follow:</p>
    <ul class="social-links">
      
        <li><a class="social-tooltip" title="github" href="https://github.com/godera" target="_blank"><i class="icon fa fa-github"></i></a></li>
      
    </ul>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2015/11/16/navigationItem的正确用法/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">newer</strong>
      <p class="article-nav-title">
        
          navigationItem的正确用法
        
      </p>
      <i class="icon fa fa-chevron-right" id="icon-chevron-right"></i>
    </a>
  
  
    <a href="/2015/11/06/iOS-检测版本更新代码-OC/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">older</strong>
      <p class="article-nav-title">iOS 检测版本更新代码-OC</p>
      <i class="icon fa fa-chevron-left" id="icon-chevron-left"></i>
    </a>
  
</nav>

  
  <div class="widgets-container">
    
      
  <div class="widget-wrap">
    <h3 class="widget-title">recents</h3>
    <div class="widget">
      <ul id="recent-post" class="">
        
          <li>
            
            <div class="item-thumbnail">
              
<a href="/2016/11/30/Markdown-技巧汇总（持续帖）/" class="thumbnail">
  
    <span class="thumbnail-image thumbnail-none"></span>
  
</a>

            </div>
            
            <div class="item-inner">
              <p class="item-category"><a class="article-category-link" href="/categories/iOS/">iOS</a></p>
              <p class="item-title"><a href="/2016/11/30/Markdown-技巧汇总（持续帖）/" class="title">Markdown 技巧汇总（持续帖）</a></p>
              <p class="item-date"><time datetime="2016-11-30T05:10:18.000Z" itemprop="datePublished">2016-11-30</time></p>
            </div>
          </li>
        
          <li>
            
            <div class="item-thumbnail">
              
<a href="/2016/11/27/CocoaPods-指南/" class="thumbnail">
  
    <span class="thumbnail-image thumbnail-none"></span>
  
</a>

            </div>
            
            <div class="item-inner">
              <p class="item-category"><a class="article-category-link" href="/categories/iOS/">iOS</a></p>
              <p class="item-title"><a href="/2016/11/27/CocoaPods-指南/" class="title">CocoaPods 指南</a></p>
              <p class="item-date"><time datetime="2016-11-27T11:03:26.000Z" itemprop="datePublished">2016-11-27</time></p>
            </div>
          </li>
        
          <li>
            
            <div class="item-thumbnail">
              
<a href="/2016/04/16/OC-和-Swift-的混用方法/" class="thumbnail">
  
    <span class="thumbnail-image thumbnail-none"></span>
  
</a>

            </div>
            
            <div class="item-inner">
              <p class="item-category"><a class="article-category-link" href="/categories/iOS/">iOS</a></p>
              <p class="item-title"><a href="/2016/04/16/OC-和-Swift-的混用方法/" class="title">OC 和 Swift 的混用方法</a></p>
              <p class="item-date"><time datetime="2016-04-16T11:11:42.000Z" itemprop="datePublished">2016-04-16</time></p>
            </div>
          </li>
        
          <li>
            
            <div class="item-thumbnail">
              
<a href="/2016/04/11/ReactiveCocoa-简单总结/" class="thumbnail">
  
    <span class="thumbnail-image thumbnail-none"></span>
  
</a>

            </div>
            
            <div class="item-inner">
              <p class="item-category"><a class="article-category-link" href="/categories/iOS/">iOS</a></p>
              <p class="item-title"><a href="/2016/04/11/ReactiveCocoa-简单总结/" class="title">ReactiveCocoa 简单总结</a></p>
              <p class="item-date"><time datetime="2016-04-11T03:00:29.000Z" itemprop="datePublished">2016-04-11</time></p>
            </div>
          </li>
        
          <li>
            
            <div class="item-thumbnail">
              
<a href="/2016/04/09/从汉语字面理解-观察者模式-和-订阅者模式-的区别/" class="thumbnail">
  
    <span class="thumbnail-image thumbnail-none"></span>
  
</a>

            </div>
            
            <div class="item-inner">
              <p class="item-category"><a class="article-category-link" href="/categories/Unix-Linux/">Unix_Linux</a></p>
              <p class="item-title"><a href="/2016/04/09/从汉语字面理解-观察者模式-和-订阅者模式-的区别/" class="title">从汉语字面理解 观察者模式 和 订阅者模式 的区别</a></p>
              <p class="item-date"><time datetime="2016-04-09T10:19:20.000Z" itemprop="datePublished">2016-04-09</time></p>
            </div>
          </li>
        
      </ul>
    </div>
  </div>

    
      
  <div class="widget-wrap widget-list">
    <h3 class="widget-title">archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/11/">November 2016</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/04/">April 2016</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/03/">March 2016</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/02/">February 2016</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/01/">January 2016</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/12/">December 2015</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/11/">November 2015</a><span class="archive-list-count">6</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/10/">October 2015</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/09/">September 2015</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/08/">August 2015</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/06/">June 2015</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/05/">May 2015</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/04/">April 2015</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/03/">March 2015</a><span class="archive-list-count">36</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/02/">February 2015</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/01/">January 2015</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2014/10/">October 2014</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2012/06/">June 2012</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2011/10/">October 2011</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2010/06/">June 2010</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2008/08/">August 2008</a><span class="archive-list-count">1</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget-wrap widget-float">
    <h3 class="widget-title">tag cloud</h3>
    <div class="widget tagcloud">
      <a href="/tags/JS/" style="font-size: 10px;">JS</a> <a href="/tags/Unix-Linux/" style="font-size: 14px;">Unix_Linux</a> <a href="/tags/iOS/" style="font-size: 20px;">iOS</a> <a href="/tags/哲学辨思/" style="font-size: 16px;">哲学辨思</a> <a href="/tags/数据库/" style="font-size: 10px;">数据库</a> <a href="/tags/文字文化/" style="font-size: 18px;">文字文化</a> <a href="/tags/生活感悟/" style="font-size: 14px;">生活感悟</a> <a href="/tags/随心随性/" style="font-size: 12px;">随心随性</a> <a href="/tags/默认标签/" style="font-size: 10px;">默认标签</a>
    </div>
  </div>


    
      
  <div class="widget-wrap widget-list">
    <h3 class="widget-title">links</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="http://hexo.io">Hexo</a>
          </li>
        
      </ul>
    </div>
  </div>


    
  </div>
</aside>
        </div>
      </div>
    </div>
    <footer id="footer">
  
  <div class="container">
    <div class="container-inner">
      <a id="back-to-top" href="javascript:;"><i class="icon fa fa-angle-up"></i></a>
      <div class="credit">
        <h1 class="logo-wrap">
          <a href="/" class="logo"></a>
        </h1>
        <p>&copy; 2016 梁逊</p>
        <p>Powered by <a href="//hexo.io/" target="_blank">Hexo</a>. Theme by <a href="//github.com/ppoffice" target="_blank">PPOffice</a></p>
      </div>
    </div>
  </div>
</footer>
    


  <script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>



  <script src="/fancybox/jquery.fancybox.pack.js"></script>



  <script src="/scrollLoading/jquery.scrollLoading.js"></script>
  <script src="/scrollLoading/main.js"></script>




<script src="/js/html-patch.js"></script>
<script src="/js/script.js"></script>

  </div>
</body>
</html>
